package com.luke.xiaotiaowa.modules.ums.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luke.xiaotiaowa.events.XtwEvents;
import com.luke.xiaotiaowa.modules.ums.cache.UmsPermCacheService;
import com.luke.xiaotiaowa.modules.ums.entity.UmsAdminRoleRelationEntity;
import com.luke.xiaotiaowa.modules.ums.entity.UmsRoleEntity;
import com.luke.xiaotiaowa.modules.ums.entity.UmsRolePermRelationEntity;
import com.luke.xiaotiaowa.modules.ums.mapper.UmsAdminRoleRelationMapper;
import com.luke.xiaotiaowa.modules.ums.mapper.UmsRoleMapper;
import com.luke.xiaotiaowa.modules.ums.mapper.UmsRolePermRelationMapper;
import com.luke.xiaotiaowa.modules.ums.service.UmsRolePermRelationService;
import com.luke.xiaotiaowa.modules.ums.service.UmsRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 后台用户角色表 服务实现类
 * </p>
 *
 * @author xiaotiaowa
 * @since 2023-03-24
 */
@Service
public class UmsRoleServiceImpl  extends ServiceImpl<UmsRoleMapper, UmsRoleEntity> implements UmsRoleService {
    
    @Resource
    private UmsRoleMapper roleMapper;
    @Resource
    private UmsAdminRoleRelationMapper adminRoleRelationMapper;
    @Resource
    private UmsRolePermRelationMapper rolePermRelationMapper;
    @Resource
    private UmsRolePermRelationService rolePermRelationService;
    @Resource
    private UmsPermCacheService permCacheService;

    @Override
    public List<UmsRoleEntity> getRolesByAdminId(long adminId) {
        return roleMapper.selectRolesByAdminId(adminId);
    }

    @Override
    public List<UmsRoleEntity> selectUmsRole(IPage<UmsRoleEntity> page, String keyword) {
        return roleMapper.selectListByParams(page, keyword);
    }

    @Override
    public UmsRoleEntity selectUmsRole(long id) {
        var role =  roleMapper.selectById(id);
        XtwEvents.BAD_REQUEST.get().message("角色不存在")
                .ifTrueThrow(ObjectUtil.isNull(role));
        return role;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UmsRoleEntity addUmsRole(UmsRoleEntity role) {
        var oldRole = selectUmsRoleByName(role.getName());
        XtwEvents.BAD_REQUEST.get().message("角色名已存在").ifTrueThrow(ObjectUtil.isNotNull(oldRole));
        roleMapper.insert(role);
        return role;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UmsRoleEntity modUmsRole(long id, UmsRoleEntity role) {
        role.setId(id);
        var oldRole = selectUmsRole(id);
        var roleByName = selectUmsRoleByName(role.getName());
        XtwEvents.BAD_REQUEST.get().message("角色名已存在")
                .ifTrueThrow(ObjectUtil.isNotNull(roleByName) && !roleByName.getId().equals(role.getId()));
        role.setVersion(oldRole.getVersion());
        roleMapper.updateById(role);
        return role;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delUmsRole(long id) {
        var role = selectUmsRole(id);
        adminRoleRelationMapper.deleteByRoleId(role.getId());
        roleMapper.deleteById(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activateUmsRole(long id) {
        var role = selectUmsRole(id);
        permCacheService.delByRoleId(id);
        role.setStatus(true);
        roleMapper.updateById(role);
        permCacheService.delByRoleIdAsync(id, 3000);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void suspendedUmsRole(long id) {
        var role = selectUmsRole(id);
        permCacheService.delByRoleId(id);
        role.setStatus(false);
        roleMapper.updateById(role);
        permCacheService.delByRoleIdAsync(id, 3000);
    }

    @Override
    public UmsRoleEntity selectUmsRoleByName(String name) {
        return roleMapper.selectByUsername(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignPerm(long roleId, List<Long> perms) {
        var role = selectUmsRole(roleId);
        permCacheService.delByRoleId(roleId);
        rolePermRelationMapper.deleteByRoleId(roleId);
        var relations = perms.stream()
                .map(r -> {
                    var relation = new UmsRolePermRelationEntity();
                    relation.setRoleId(role.getId());
                    relation.setPermId(r);
                    return relation;
                }).collect(Collectors.toList());
        Optional.of(relations)
                .filter(v -> v.size() > 0)
                .ifPresent(v -> rolePermRelationService.saveBatch(relations));
        permCacheService.delByRoleIdAsync(roleId, 3000);
    }
}
